#include <iostream>

#include <transport/TSocket.h>
#include <boost/lexical_cast.hpp>
#include <transport/TBufferTransports.h>
#include <protocol/TBinaryProtocol.h>

#include "base/object_pool.h"
#include "base/object_pool.h"

using namespace base;

using namespace apache::thrift;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;

template <typename ClientType>
class ClientPool : public ObjectPool<ClientType> {
  bool ParseAddr(const std::string & addr, std::string * host, int * port) const {
    size_t pos = addr.find_first_of(':');
    if (pos == std::string::npos) {
      return false;
    }
    *host = addr.substr(0, pos);

    try {
      *port = boost::lexical_cast<short>(addr.substr(pos + 1));
    } catch (boost::bad_lexical_cast &) {
      return false;
    }
    return true;
  }
 public:
  virtual ClientType * Create(const std::string & key) {
    std::string host;
    int port;

    if (!ParseAddr(key, &host, &port)) {
      LOG_WARN("bad service addr : " << key);
      return NULL;
    }

    boost::shared_ptr<TSocket> socket(new TSocket(host.c_str(), port));

    int timeout = 200;
    socket->setConnTimeout(timeout);
    socket->setSendTimeout(timeout);
    socket->setRecvTimeout(timeout);
    socket->setNoDelay(true);
    socket->setLinger(false, 0);

    boost::shared_ptr<TTransport> transport(new TFramedTransport(socket));
    boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));

    try {
      transport->open();
    } catch (TTransportException & e) {
      LOG_WARN("Thrift conn open error addr=" << socket->getHost() 
          << ":" << socket->getPort() << " " << e.what());
      return NULL;
    } catch (...) {
      LOG_WARN("Thrift conn open unknown error. addr=" << socket->getHost() 
          << ":" << socket->getPort());
      return NULL;
    }


    return new ClientType(protocol);
  }

  virtual void Destroy(ClientType * p) {
    // transport 的析够会调用close()
    delete p;
  }
};


